package com.donleo.oauth2.gateway.filter;

import com.alibaba.fastjson.JSONObject;
import com.donleo.oauth2.common.utils.EncryptUtil;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.oauth2.provider.OAuth2Authentication;
import org.springframework.security.oauth2.provider.OAuth2Request;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author liangd
 * @since 2021-03-11 11:44
 */
public class AuthFilter extends ZuulFilter {
    @Override
    public String filterType() {
        //在访问前判断
        return "pre";
    }

    @Override
    public int filterOrder() {
        //值越小优先级越高
        return 0;
    }

    @Override
    public boolean shouldFilter() {
        //所有的请求都拦截
        return true;
    }

    @Override
    public Object run() {
        RequestContext context = RequestContext.getCurrentContext();
        //从安全上下文中拿到用户身份对象
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        if (!(authentication instanceof OAuth2Authentication)) {
            return null;
        }
        OAuth2Authentication oAuth2Authentication = (OAuth2Authentication) authentication;
        Authentication userAuthentication = oAuth2Authentication.getUserAuthentication();
        //取出用户身份信息
        String principal = userAuthentication.getName();
        List<String> authorities = new ArrayList<>();
        //从userAuthentication中取出权限，放进authorities中
        userAuthentication.getAuthorities().forEach(c -> authorities.add(c.getAuthority()));
        OAuth2Request oAuth2Request = oAuth2Authentication.getOAuth2Request();
        Map<String, String> requestParameters = oAuth2Request.getRequestParameters();

        Map<String, Object> jsonToken = new HashMap<>(requestParameters);
        jsonToken.put("principal", principal);
        jsonToken.put("authorities", authorities);
        //将用户信息及其拥有的权限转成json对象，并加密成Base64格式，放进请求头中
        context.addZuulRequestHeader("json-token", EncryptUtil.encodeUTF8StringBase64(JSONObject.toJSONString(jsonToken)));
        return null;
    }
}
